<?php


namespace App\Services\SDK;


use App\Exceptions\SDKNameNotFoundException;
use App\Models\Order;
use App\Models\SdkConfig;
use GuzzleHttp\Client;
use Illuminate\Support\Arr;

abstract class BaseSDK
{
    /**
     * @var string[]
     */

    public static $loginVerifyUrl
        = [
            'test' => '',
            'prod' => '',
        ];

    const SDK_NAME = '';
    /**
     * @var string 渠道方提供的 api id
     */
    protected $appId = '';
    /**
     * @var string 渠道方提供的 key
     */
    protected $appKey = '';

    protected $dispatchApi = '';
    protected $gameServerKey = '';

    protected $http;

    /**
     * BaseSDK constructor.
     * @param Client $client
     */
    public function __construct(Client $client)
    {
        $this->http = $client;
    }

    /**
     * @return string
     */
    public function getDispatchApi()
    {
        return $this->dispatchApi;
    }

    public function getGameServerKey()
    {
        return $this->gameServerKey;
    }

    /**
     * @param $value
     * @return string
     */
    public function setDispatchApi($value)
    {
        $this->dispatchApi = $value;
    }

    public function setGameServerKey($value)
    {
        $this->gameServerKey = $value;
    }

    /**
     * @return string
     */
    public function getAppId()
    {
        return $this->appId;
    }

    /**
     * @return string
     */
    public function getAppKey()
    {
        return $this->appKey;
    }

    public function setAppId($appId)
    {
        $this->appId = $appId;
        return $this;
    }

    public function setAppKey($appKey)
    {
        $this->appKey = $appKey;
        return $this;
    }

    public function loadConfig()
    {
        if (static::SDK_NAME && $config = SdkConfig::where('code', static::SDK_NAME)->first()) {
            $this->setAppId(trim($config->app_id));
            $this->setAppKey(trim($config->app_key));
            $this->setDispatchApi(trim($config->dispatch_api));
            $this->setGameServerKey(trim($config->game_key));
        } else {
            throw new SDKNameNotFoundException();
        }
        return $this;
    }

    public function getVerifyLoginUrl()
    {
        if (app()->environment() == 'production') {
            return Arr::get(static::$loginVerifyUrl, 'prod');
        }
        return Arr::get(static::$loginVerifyUrl, 'test');
    }

    abstract public function makeSign($params);

    abstract public function createOrFirstOrder($params);

    /**
     * @param Order $order
     * @return bool
     */
    public function dispatchOrder(Order $order)
    {
        $client = new Client();

        $url = $this->getDispatchApi();

        $body = [
            'appId'      => $this->getAppId(),
            'serverName' => $order->server_id,
            'roleName'   => $order->role_name,
            'qty'        => (int)($order->money * 100),
            'orderNo'    => $order->sdk_order_no,
        ];

        $appKey = $this->getGameServerKey();

        $body['sign'] = md5($body['appId'] . $body['serverName'] . $body['roleName'] . $body['qty'] . $body['orderNo'] . $appKey);

        $response = $client->request('POST', $url, [
            'headers'        => [
                'Content-Type' => 'application/x-www-form-urlencoded',
            ],
            'body'           => json_encode($body),
            'decode_content' => false
        ])->getBody()->getContents();


        $order->response = $response;
        $response        = json_decode($response, true);

        if (Arr::get($response, 'Code') === 0) {
            $order->status = Order::SUCCESS;
            $order->save();
        } else {
            $order->status = Order::FAILED;
            $order->save();
        }

        return Arr::get($response, 'Code') === 0;

    }
}
